package com.lge.clock.alarmclock;

import java.util.Calendar;
import java.util.Date;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.Log;

import com.lge.clock.R;
import com.lge.clock.util.CommonUtil;
import com.lge.clock.util.CommonUtil.OPERATOR;


/**
 * The Alarms provider supplies info about Alarm Clock settings
 * @author sungtan.back
 */
public class Alarms implements AlarmConstants {
	/**
	 * Field ACTION_ALARM_CHANGED.
	 * (value is ""android.intent.action.ALARM_CHANGED"")
	 */
	public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
    /**
     * Field ALARM_ALERT_ACTION.
     * (value is ""com.lge.clock.alarmclock"")
     */
    public static final String ALARM_ALERT_ACTION	= "com.lge.clock.alarmclock";
    /**
     * Field ALARM_STOP.
     * (value is ""shutdown_alarmclock"")
     */
    public static final String ALARM_STOP = "shutdown_alarmclock";
    /**
     * Field CONTENT_ALARMS_URI_STRING.
     * (value is ""content://com.lge.clock.alarmclock.ALProvider/alarms"")
     */
//    public static final String CONTENT_ALARMS_URI_STRING = "content://com.lge.clock.alarmclock.ALProvider/alarms";
    public static final Uri CONTENT_ALARMS_URI = Uri.parse(ALProvider.CONTENT_ALARMS_URI_STRING.concat("?queryType=1"));
    
    private static final String DM12 = "E h:mm aa";
    private static final String DM24 = "E kk:mm";
    private static final String M12 = "h:mm aa";
    // Shared with DigitalClock
    /**
     * Field M24.
     * (value is ""kk:mm"")
     */
    private static final String M24 = "kk:mm";  
    private static String temp_Tone = "";
    private static String temp_Vib  = ""; 
    private static String temp_Memo  = ""; 
    private static String temp_Puzzle = "";
    
/* I3.0 Code [START] */
    private static String temp_AlarmVolume ="";
/* I3.0 Code [END] */
    
    private static final String TAG = "Alarms";
    
    /**
     * Field CANCEL_SNOOZE.
     * (value is ""cancel_snooze_alarmclock"")
     */
    public static final String CANCEL_SNOOZE = "cancel_snooze_alarmclock";
    
    /**
     * 2012.03.16 suein1209.kim
     */
    public static final String RINGTONE_CONTAIN_ALARM = "RINGTONE_CONTAIN_ALARM"; 
    
    /** 
     * Managing Repeat days.
     * Mapping from days in this application (where Monday is 0) to
     * days in DateUtils (where Monday is 2).
     * @author LGE Cappuccino
     */
    public static class DaysOfWeek {
    	private static final int DAY_IDX_MON = 0;
    	private static final int DAY_IDX_TUE = 1;
    	private static final int DAY_IDX_WED = 2;
    	private static final int DAY_IDX_THU = 3;
    	private static final int DAY_IDX_FRI = 4;
    	private static final int DAY_IDX_SAT = 5;
    	private static final int DAY_IDX_SUN = 6;
    	
    	private final int[] day_Map = new int[] {
    	        Calendar.MONDAY,
    	        Calendar.TUESDAY,
    	        Calendar.WEDNESDAY,
    	        Calendar.THURSDAY,
    	        Calendar.FRIDAY,
    	        Calendar.SATURDAY,
    	        Calendar.SUNDAY,
    	};
    	
        /**
         * Field mDays.
         * Bitmask of all repeating days
         */
        int mDays;
        /**
         * Days of week coded as single int, convenient for DB
         * storage:
         *
         * 0x00:  no day
         * 0x01:  Monday
         * 0x02:  Tuesday
         * 0x04:  Wednesday
         * 0x08:  Thursday
         * 0x10:  Friday
         * 0x20:  Saturday
         * 0x40:  Sunday
         */
        DaysOfWeek() {
            this(0);
        }

        /**
         * Constructor for DaysOfWeek.
         * @param days int
         */
        public DaysOfWeek(int days) {
            mDays = days;
        }

        /**
         * Make repeat days string, using DateUtils instead of DateFormatSymbols
         */
		public String toString(Context context) { // , boolean showNever) {
			if(CommonUtil.isHebrewLanguage()){
				return toStringForHebrew(context);
			}
			
			StringBuilder ret = new StringBuilder(CommonUtil.STR_BUF_DEF_SIZE);
			
			/* no days */
			if (mDays == 0) {
				return context.getText(R.string.never).toString();
				/* every day */
			} else if (mDays == 0x7f) { // 127
				return context.getText(R.string.every_day).toString();
			} else if (mDays == 96) { // weekend
				return context.getText(R.string.weekends).toString();
			} else if (mDays == 63) { // MO - SA
				return getStringPeriod(DAY_IDX_MON, DAY_IDX_SAT);
			} else if (mDays == 31) { // MO - FR
				return getStringPeriod(DAY_IDX_MON, DAY_IDX_FRI);
			} else if (mDays == 62) { // TU - SA
				return getStringPeriod(DAY_IDX_TUE, DAY_IDX_SAT);
			} else if (mDays == 126) { // TU - SU
				return getStringPeriod(DAY_IDX_TUE, DAY_IDX_SUN);
			} else if (mDays == 124) { // WE - SU
				return getStringPeriod(DAY_IDX_WED, DAY_IDX_SUN);
			}

			/* count selected days */
			int dayCount = 0, days = mDays;
			while (days > 0) {
				if ((days & 1) == 1)
					dayCount++;
				days >>= 1;
			}

			// BASICPKG_S AlarmClock [sungtan.back@lge.com 110415] using
			// DateUtils instead of DateFormatSymbols
			/* short or long form? */
			// DateFormatSymbols dfs = new DateFormatSymbols();
			// String[] dayList = (dayCount > 1) ? dfs.getShortWeekdays() :
			// dfs.getWeekdays();

			// LGE_MERGE_S kiwon79.seo 2011. 3. 9.
			// MOD : [Thunder P500 GingerBread][DeskClock] BugFix : weekday
			// representation issue
			int weekDayLengthType = (dayCount > 1) ? DateUtils.LENGTH_MEDIUM
					: DateUtils.LENGTH_LONG;
			// LGE_MERGE_E kiwon79.seo 2011. 3. 9.

			/* selected days */
			for (int i = 0; i < 7; i++) {
				if ((mDays & (1 << i)) != 0) {
					// ret.append(dayList[DAY_MAP[i]]);
					ret.append(DateUtils.getDayOfWeekString(day_Map[i],
							weekDayLengthType));
					dayCount -= 1;
					if (dayCount > 0)
						ret.append(context.getText(R.string.day_concat));
				}
			}
			// BASICPKG_E

			return ret.toString();
		}
		
		private String toStringForHebrew(Context context){
			if (mDays == 0) {
				return context.getText(R.string.never).toString();
				/* every day */
			} else if (mDays == 0x7f) { // 127
				return context.getText(R.string.every_day).toString();
			} else if (mDays == 48) { // weekend
				return context.getText(R.string.weekends).toString();
			} else if (mDays == 95) { // SU - FR
				return getStringPeriod(DAY_IDX_SUN, DAY_IDX_FRI);
			} else if (mDays == 79) { // SU - TH
				return getStringPeriod(DAY_IDX_SUN, DAY_IDX_THU);
			} else if (mDays == 31) { // MO - FR
				return getStringPeriod(DAY_IDX_MON, DAY_IDX_FRI);
			} else if (mDays == 63) { // MO - SA
				return getStringPeriod(DAY_IDX_MON, DAY_IDX_SAT);
			} else if (mDays == 62) { // TU - SA
				return getStringPeriod(DAY_IDX_TUE, DAY_IDX_SAT);
			}
			
			StringBuilder ret = new StringBuilder(CommonUtil.STR_BUF_DEF_SIZE);
			
			int dayCount = 0, days = mDays;
			while (days > 0) {
				if ((days & 1) == 1)
					dayCount++;
				days >>= 1;
			}
			int weekDayLengthType = (dayCount > 1) ? DateUtils.LENGTH_MEDIUM
					: DateUtils.LENGTH_LONG;
			
			if((mDays & (1 << DAY_IDX_SUN)) != 0){
				ret.append(DateUtils.getDayOfWeekString(day_Map[DAY_IDX_SUN],
						 weekDayLengthType));
				dayCount -= 1;
				if (dayCount > 0){
					ret.append(context.getText(R.string.day_concat));
				}
			}
			
			for (int i = 0; i < DAY_IDX_SUN; i++) {
				if ((mDays & (1 << i)) != 0) {
					// ret.append(dayList[DAY_MAP[i]]);
					ret.append(DateUtils.getDayOfWeekString(day_Map[i],
							weekDayLengthType));
					dayCount -= 1;
					if (dayCount > 0){
						ret.append(context.getText(R.string.day_concat));
					}
				}
			}
			return ret.toString();
		}
		
		private String getStringPeriod(int fromDay, int toDay) {
			StringBuilder ret = new StringBuilder();
			ret.append(DateUtils.getDayOfWeekString(day_Map[fromDay],
					DateUtils.LENGTH_MEDIUM));
			ret.append(" - ");
			ret.append(DateUtils.getDayOfWeekString(day_Map[toDay],
					DateUtils.LENGTH_MEDIUM));
			return ret.toString();
		}

        /**
         * @param day Mon=0 ... Sun=6
        
         * @return true if given day is set */
        public boolean isSet(int day) {
            return ((mDays & (1 << day)) > 0);
        }

        /**
         * Method set.
         * @param day int
         * @param set boolean
         */
        public void set(int day, boolean set) {
            if (set) {
                mDays |= (1 << day);
            } else {
                mDays &= ~(1 << day);
            }
        }

        /**
         * Method set.
         * @param dow DaysOfWeek
         */
        public void set(DaysOfWeek dow) {
            mDays = dow.mDays;
        }

        public int getCoded() {
            return mDays;
        }

        /**
         * Method equalDaysofWeek.
         * @param dow DaysOfWeek
        
         * @return boolean */
        public boolean equalDaysofWeek(DaysOfWeek dow) {
            return mDays == dow.mDays;
        }

        // Returns days of week encoded in an array of booleans.
        public boolean[] getBooleanArray() {
            boolean[] ret = new boolean[7];
            for (int i = 0; i < 7; i++) {
                ret[i] = isSet(i);
            }
            return ret;
        }

        public void setCoded(int days) {
            mDays = days;
        }

        /**
         * @return true if alarm is set to repeat
         */
        public boolean isRepeatSet() {
            return mDays != 0;
        }

        /**
         * @return true if alarm is set to repeat every day
         */
        public boolean isEveryDaySet() {
            return mDays == 0x7f;
        }

        /**
         * returns number of days from today until next alarm
         * @param c must be set to today
        
         * @return int */
        public int getNextAlarm(Calendar c) {
            if (mDays == 0) return -1;
            int today = (c.get(Calendar.DAY_OF_WEEK) + 5) % 7;

            int day, dayCount;
            for (dayCount = 0; dayCount < 7; dayCount++) {
                day = (today + dayCount) % 7;
                if ((mDays & (1 << day)) > 0) {
                    break;
                }
            }
            return dayCount;
        }
    }
    
    /**
     * Off-> On
     * @param context
     * @param id
     * @param enabled
     */
    public static void enableAlarm(final Context context, final int id, boolean enabled) {
    	synchronized ( context ) {
            // enabled value & id value  update 
            enableAlarmInternal(context, id, enabled);

            // enabled alarm setting
            setNextAlert(context);
    	}
    }
    
    private static void enableAlarmInternal( final Context context, final int id, boolean enabled) {   
    //============================================================================================================================	
        ContentResolver resolver = context.getContentResolver();
        ////////////////////////////////////////////////////////////////////////////
        ContentValues values = new ContentValues(1);
        values.put("enabled", enabled ? 1 : 0);
              
        resolver.update(ALProvider.CONTENT_ALARMS_URI, values, "_id=" + id, null);
        resolver.update(ALProvider.CONTENT_CALCU_URI,  values, "aid=" + id + "  and aindex = 0", null);     
                          
        /**
		 * snooze data delete
		 */
    	NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
		nm.cancel(id);
		resolver.delete(ALProvider.CONTENT_CALCU_URI, "aid=" + id + "  and aindex > 0",  null);       
    }        
    
    /**
     * Off update
     */
	private static void enableAlarmInternalOff( final Context context, final int id, boolean tag) { 
    //============================================================================================================================	
		ContentResolver resolver = context.getContentResolver();
        ////////////////////////////////////////////////////////////////////////////
        ContentValues values = new ContentValues(1);
        values.put("enabled", 0);

        synchronized ( context ) {
        	resolver.update(ALProvider.CONTENT_ALARMS_URI, values, "_id=" + id, null);
            resolver.update(ALProvider.CONTENT_CALCU_URI,  values, "aid=" + id + "  and aindex = 0", null);
            
            /**
    		 * snooze data delete
    		 */
            if( tag == false ) {
    	    	NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    			nm.cancel(id);
            }
    		resolver.delete(ALProvider.CONTENT_CALCU_URI, "aid=" + id + "  and aindex > 0",  null);
        }
    }        

    /**
     * current snooze (current time > old) = delete 
     * boot.
     * @param context Context
     */
    public static void disableExpiredAlarms(final Context context , boolean isBooting) {//P930_TD#13208_20110712 disable icons of expired Alarms after reboot hyunjung78.park
    	long now = System.currentTimeMillis();
    	
    	ContentResolver resolver = null;
    	
    	//changed by essin@lge.com 2010.11.29
    	try {
    		resolver = context.getContentResolver();
    		resolver.delete(ALProvider.CONTENT_CALCU_URI, " time <= " + now + "  and  aindex > 0",  null);	
    	}
    	catch(Exception e) {
    		Log.e(TAG, "Alarms -> disableExpiredAlarms : "+e.getMessage());
    		return ;
    	} //End Of try

		
        Log.d(TAG, " --- disableExpiredAlarms!!! isBooting : "+isBooting);
		//[START]P930_TD#13208_20110712 disable icons of expired Alarms after reboot hyunjung78.park
		if (isBooting == false) {
			Log.d(TAG, " --- disableExpiredAlarms!!! isBooting  return");
            return;
        }

		String[] snoozeIDs = null;
        Cursor cursor = null;
        int count = 0;
        try {
            cursor = resolver.query(Uri.parse(("content://com.lge.clock.alarmclock.ALProvider/calcus")
                    .concat("?calcuqueryType=3")), Calcus_Cols, " aindex > 0 ", null, null);
            if (cursor != null) {
                count = cursor.getCount();
                int index = -1;
                if (count > 0) {
                    snoozeIDs = new String[count];
                    if (cursor.moveToFirst()) {
                        do {  
                            snoozeIDs[++index] = cursor.getString(0);
                        } while (cursor.moveToNext());
                    }
                }
            }
        } catch (Exception e) {
        
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
 
        try {
           
            cursor = resolver.query(Uri.parse(("content://com.lge.clock.alarmclock.ALProvider/calcus")
                    .concat("?queryType=1")), PROJECTION,
                    "enabled = '1'  and  daysofweek = 0 and status = 'A'", null, "time");
			if (cursor != null) {
				count = cursor.getCount();
	            Log.d(TAG, "count ===>" + count);
	             
	            if (count > 0) {
	                if (cursor.moveToFirst()) {
	                    do {  
	                        Log.d(TAG, " aid : "+cursor.getInt(0) + " daysofweek : " + cursor.getInt(1)
	                                + " enabled :  " + cursor.getInt(2) + " time :  " + cursor.getLong(3) + "status "
	                                + cursor.getInt(4));
	                       
	                        Log.e(TAG, "alarm set time : " + cursor.getLong(3) + "<=" + "current time : " + now);
	                        if (cursor.getLong(3) <= now) {
	                            boolean snoozeYN = false;
	                            for (int i = 0; snoozeIDs != null && i < snoozeIDs.length; i++) {
	                                if (snoozeIDs[i].equals(cursor.getString(0))) {
	                                    snoozeYN = true;
	                                    break;
	                                }
	                            } 
								int id = cursor.getInt(0);//aid 
	                            if (snoozeYN == false) {
	                                
	                                Log.d(TAG, " ===========Snooze NO==>" + id + " / " + cursor.getInt(1));
	                                ContentValues values = new ContentValues(1);
	                                values.put("enabled", 0);
	                                //resolver.update(ALProvider.CONTENT_CALCU_URI, values, "_id=" + id
	                                //        + "  and aindex = 0", null);
	                                 resolver.update(ALProvider.CONTENT_ALARMS_URI, values, "_id=" + id,
                                        null);
	                                resolver.update(ALProvider.CONTENT_CALCU_URI, values, "aid=" + id
	                                        + "  and aindex = 0", null);
	                            } else { 
	                                 
	                                Log.d(TAG, " ============Snooze Yes==>" + id + " / " + cursor.getInt(1));
	                                ContentValues values = new ContentValues(1);
	                                values.put("enabled", 1);
	                                resolver.update(ALProvider.CONTENT_ALARMS_URI, values, "_id=" + id,
	                                        null);
	                            }

	                        }
	                    } while (cursor.moveToNext());
	                } 
	            } 
			}
            
        } catch (Exception e) {
        	e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

		//[END]P930_TD#13208_20110712 disable icons of expired Alarms after reboot hyunjung78.park
    }
    //[START]P930_TD#13208_20110712 disable icons of expired Alarms after reboot hyunjung78.park
    private static final String[] PROJECTION = new String[] {
            "aid", "daysofweek", "enabled", "time", "status"
    };
    private static final String[] Calcus_Cols = new String[] {
        "aid"
    };
	//[END]P930_TD#13208_20110712 disable icons of expired Alarms after reboot hyunjung78.park
    /**
     * current snooze (booting, notification regist)
     * @param context
     */  
	public static void snoozeActivating(Context context) {
		/**
		 * snooze service check
		 */
//		final String[] cols = new String[] { "aid", "time" };
		final String[] alarmNeedColums = { "memo" };

		ContentResolver resolver = context.getContentResolver();

		// changed by essin@lge.com 2010.11.29
		int scount = 0;
		
		Cursor cc = null;
		// [mo2sangbong.lee][1455] 2011.10.18 START
		SQLiteDatabase database = null;
		
		try {
			try {
				database = ALProvider.getmOpenHelper().getReadableDatabase();
				cc = database
						.rawQuery(
								"SELECT aid, min(time) FROM calcus WHERE status='S' GROUP BY aid ORDER BY aid, time",
								null);
				if (cc != null) {// [hyunjung78.park] 2011.08.09 cursor null check
					scount = cc.getCount();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				Log.d(TAG, "snoozeActivating scount==>" + scount);
				if (scount == 0 && cc != null) {
					cc.close();
					cc = null;
				}
				if (database != null) {
					database.close();
				}
			}
			// [mo2sangbong.lee][1455] 2011.10.18 END
			if (scount == 0)
				return;

			int aid = 0;
			long time = 0l;
			String memo = "";
			NotificationManager nm = (NotificationManager) context
					.getSystemService(Context.NOTIFICATION_SERVICE);

			if (cc != null && cc.moveToFirst()) {// [hyunjung78.park] 2011.08.09
													// cursor null check
				do { // Get the field values
					aid = cc.getInt(0);
					time = cc.getLong(1);
					nm.cancel(aid);
					Log.d(TAG, "====>>>>>>>  hide snooze aid : " + aid
							+ " / time = " + time);

					Cursor sss = null;
					try {
						sss = resolver.query(ALProvider.CONTENT_ALARMS_URI,
								alarmNeedColums, "_id=" + aid, null, null);
						if (sss != null) {// [hyunjung78.park] 2011.08.09 cursor
											// null check
							if (sss.moveToFirst()) {
								do {
									memo = sss.getString(0);
								} while (sss.moveToNext());
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						if (sss != null)
							sss.close();
					}

					// Notify the user that the alarm has been snoozed.
					Intent cancelSnooze = new Intent(context, ALReceiver.class);
					cancelSnooze.setAction(Alarms.CANCEL_SNOOZE);
					cancelSnooze.putExtra("id", aid);
					PendingIntent broadcast = PendingIntent.getBroadcast(
							context, aid, cancelSnooze, 0);

					// The details of our fake message
					CharSequence from = null;
					if (memo == null || "".equals(memo.trim())) {
						from = context.getText(R.string.sp_snooze_ment_NORMAL);
					} else {
						from = context.getText(R.string.sp_snooze_ment_NORMAL)
								.toString()
								+ " (" + memo + ")";
					}

					CharSequence message = context
							.getText(R.string.alarm_ment1).toString()
							+ " " + getCalendar(context, time);
					Notification notif = new Notification(
							R.drawable.stat_notify_alarm, from, 0);
					notif.setLatestEventInfo(context, from, message, broadcast);
					notif.deleteIntent = broadcast;
					notif.flags |= Notification.FLAG_AUTO_CANCEL;
					
			        if((CommonUtil.getBuildOperator() == OPERATOR.DCM 
			        		|| CommonUtil.getBuildOperator() == OPERATOR.VZW)
			        		&& CommonUtil.isPowerLEDSetInSettings(context.getContentResolver()) == 0){
			        	
			        	notif.flags |= Notification.DEFAULT_LIGHTS;
			        	
			        }else{
			        	
			        	notif.flags |= Notification.FLAG_SHOW_LIGHTS;	
			        	notif.defaults |= Notification.DEFAULT_LIGHTS;
			        	
			        } //End Of if
					// notif.ledARGB = 0xFF00FF00;
					// notif.ledOnMS = 500;
					// notif.ledOffMS = 500;
					nm.notify(aid, notif);
				} while (cc.moveToNext());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cc != null)
				cc.close();
		}
	}
    
    private static final String M24_CHECK = "kk:mm";  
	private static final String M12_CHECK = "h:mm";
//	private static String m1Format = M24_CHECK;
	
//	private static boolean getDateFormat(Context context) {
//		if (get24HourMode(context) == true) {
//			m1Format = M24_CHECK;
//			return true;
//		}    	
//		m1Format = M12_CHECK;
//		return false;
//	}
    
    private static String getCalendar(Context context, long time) {
    	Calendar aa = Calendar.getInstance();  // current date/time etc.. obtian info
    	aa.setTimeInMillis( time );
    	       
    	// is24HourFormat
    	if ( DateFormat.is24HourFormat(context) )
    	{
    		CharSequence alarmtime = DateFormat.format(M24_CHECK, aa);
	    	return (alarmtime.toString() + " " + context.getText(R.string.sp_alarm_right_ment_NORMAL).toString());
    	}
    	// is12HourFormat
    	else
    	{
    		CharSequence alarmtime = DateFormat.format(M12_CHECK, aa);
	        boolean bAPM = aa.get(Calendar.AM_PM) == 0;
	        if ( bAPM ) {
	        	return (alarmtime.toString() + " " + context.getText(R.string.sp_AM_string_NORMAL).toString()
	        			+ "." + " " + context.getText(R.string.sp_alarm_right_ment_NORMAL).toString());
	        } else {
	        	return (alarmtime.toString() + " " + context.getText(R.string.sp_PM_string_NORMAL).toString()
	        			+ "." + " " + context.getText(R.string.sp_alarm_right_ment_NORMAL).toString());
	        }
	    }
    }
     
    /**
     * Called at system startup, on time/timezone change, and whenever
     * the user changes alarm settings.  Activates snooze if set,
     * otherwise loads all alarms, activates next alert.
     */  
    
    private static final String[] CALCU_MINCOLS = {  "min(time) mintime", "min(aid) minaid" };
    private static final String[] CALCU_COLS = { "_id", "aid",  "time", "aindex", "status",  "stop" };
    private static final String[] CALCUS_TIME_COLS = new String[]  {"aid",  "hour",  "minutes", "daysofweek"  };
    
    private static boolean alarmsCalculating(final ContentResolver resolver) {
    	
        /*[START] 2012.02.09 suein1209.kim performance tuning*/
//        List<UpdateDBDataHolder> upList = new ArrayList<UpdateDBDataHolder>();
        /*[END] 2012.02.09 suein1209.kim performance tuning*/
    	
    	//changed by essin@lge.com 2010.11.29
        Cursor cc = null;
        try {
            cc = resolver.query(Uri.parse(("content://com.lge.clock.alarmclock.ALProvider/calcus").concat("?calcuqueryType=1")), CALCUS_TIME_COLS, "enabled = '1'", null, "_id");
			if (cc != null){//[hyunjung78.park] 2011.08.09 cursor null check
				if (cc.moveToFirst()) {
	                do {
	                    ContentValues values = new ContentValues(1);
	                    long time = calculateAlarm(cc.getInt(1), cc.getInt(2), new Alarms.DaysOfWeek(cc.getInt(3))).getTimeInMillis();
	                    values.put("time", time);            
	                            
	                    /*[START] 2012.02.09 suein1209.kim performance tuning*/
//	                    upList.add(new UpdateDBDataHolder(values, cc.getInt(0)));
	                    resolver.update(ALProvider.CONTENT_CALCU_URI,  values, "aid=" + cc.getInt(0) + "  and aindex = 0", null);     
	                    /*[END] 2012.02.09 suein1209.kim performance tuning*/
	                } while(cc.moveToNext());
	            }
			}
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cc != null)
                cc.close();
        }
        
        /*[START] 2012.02.09 suein1209.kim performance tuning*/
//        if(upList.size() > 0){
//        	Executors.newSingleThreadExecutor().execute(new ThTimeStateDBUpdater(resolver, upList));
//        } //End Of if
        /*[END] 2012.02.09 suein1209.kim performance tuning*/
       
    	return true;
    }     
    
    // next alarm save AlarmManager
    public static void setNextAlert(final Context context) {
    	ContentResolver resolver = context.getContentResolver(); 
    	     
    	//changed by essin@lge.com 2010.11.29
    	// alarm time update standard current time
    	
    	if(false == alarmsCalculating(resolver)) {
    		return;
    	}
    	
    	long minTime = 0l;
		int minid = 0;
    	Cursor cc = null;
		try {
			// calcuqueryType
    		cc = resolver.query(Uri.parse(("content://com.lge.clock.alarmclock.ALProvider/calcus").concat("?calcuqueryType=1")), 
								CALCU_MINCOLS, "enabled = '1' and time > 0 ", null,  null );
			if (cc != null){//[hyunjung78.park] 2011.08.09 cursor null check
				if (cc.moveToFirst()) {
	    			 do {  
	    				minTime = cc.getLong(0);
	    				minid = cc.getInt(1);
	    			} while(cc.moveToNext());
	    		}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cc != null)
				cc.close();
		}
        
		if (minTime == 0l) {
			disableAlert(context, minid);
			return ;
		}
		       
		//////////////////////////////////////////////////////////////////
		boolean multiYN = false;
		int aid = -1, temp = -1, aindex = 0;   
		int alarmCount = 1;
		String stopflag = "";
		Cursor cur = null;
		try {
			//added donggeun.kim@lge.com source 2010.12.30
			cur = resolver.query(ALProvider.CONTENT_CALCU_URI, CALCU_COLS, "enabled = '1' and time = " +  minTime, null,  "time, status, aid"  );
			if (cur != null){//[hyunjung78.park] 2011.08.09 cursor null check
				if ( cur.getCount() > 1 ) {
					Log.d(TAG, " -- OK multi -- " + cur.getCount() );
					multiYN = true;
				}else if ( cur.getCount() == 1 ) {
					Log.d(TAG, " -- No multi -- " + cur.getCount() );
				}
				
				if ( cur.moveToFirst() ) {
		    		do {
		    			if (alarmCount > 1)
		    				break;
		    			aid      = cur.getInt(1);
						aindex   = cur.getInt(3);
						stopflag = cur.getString(5);  
						  
						// in case aid input different (including duplicate alarm)
						if (aid != temp){
							temp = aid;
		            		if (aindex == 0) {
		            			Log.d(TAG, "===123 [[ incoming Alarm Type ]]=== ID : " + aid + " --- "); 
		            			alarmSet(minTime, context, aid, multiYN);
		            		} else if(aindex > 0) {
		            			Log.d(TAG, "===456[[ incoming Snooze Type ]]=== ID : " + aid + " --- "); 
		            			snoozeSet(cur.getInt(0), aid, aindex, minTime, context, stopflag, multiYN);
		            		} 
		            		alarmCount++;
						}
		    		} while(cur.moveToNext());
				}
		    }
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cur != null)
				cur.close();
		}
    }  
       
    // CALCU_COLS = { "_id", "aid",  "time", "aindex", "status"  };
    private static void alarmSet(long mintime, Context context, int aid, boolean multiYN) {
    	Intent intent = new Intent(ALARM_ALERT_ACTION);
        intent.putExtra("id", aid);
        intent.putExtra("time",   mintime);     
        intent.putExtra("gubun",  "alarm");
        int snooze = getSnoozeTime(context, aid);
        if (snooze > 0) {
        	intent.putExtra("stop",  "");
        }else {
        	intent.putExtra("stop",  "stop");
        }    
        //////////////////////////////////////////////////////////////
        intent.putExtra("snooze",  snooze); 
        intent.putExtra("memo",    temp_Memo);
        intent.putExtra("puzzle", temp_Puzzle);
        intent.putExtra("tone",    temp_Tone);
        intent.putExtra("vib",     temp_Vib); 

/* I3.0 Code [START] */
        boolean isUseVolumeControl =  CommonUtil.isUseVolumeControl();
        if(isUseVolumeControl){
        	intent.putExtra(AlarmMeta.COLUMNS.ALARM_VOLUME, temp_AlarmVolume);
        }
/* I3.0 Code [END] */

		//////////////////////////////////////////////////////////////
        if (multiYN == true) {
        	intent.putExtra("multi",  "yes"); 
        }else {
        	intent.putExtra("multi",  "no"); 
        }
        
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, mintime, sender );
        android.util.Log.d(TAG, "RTC_WAKEUP is set in Alarms.java, alarmSet");

        Calendar c3 = Calendar.getInstance();
        c3.setTimeInMillis( mintime  ) ; 
        Date dd1 =  c3.getTime();    
        Log.d(TAG, " Alarm Next ID - " + aid +  " --[[ Alarm Kind ]]----" + dd1.toString()); 

        ////////////////////////////////////////////////////////////////////////////////
        setStatusBarIcon(context, true);
        ////////////////////////////////////////////////////////////////////////////////
        String timeString = formatDayAndTime(context, c3);
        saveNextAlarm(context, timeString);
    } 
          
               
    /**
     * snooze state
     * @param pk
     * @param aid
     * @param mintime
     * @param context
     */
    // CALCU_COLS = { "_id", "aid",  "time", "aindex", "status"  };
    private static void snoozeSet(int pk, int aid, int aindex, long mintime,  Context context, String stopflag, boolean multiYN) {
    	Intent intent = new Intent(ALARM_ALERT_ACTION);
        intent.putExtra("pk", pk); 
        intent.putExtra("id", aid);   
        intent.putExtra("time",   mintime);     
        intent.putExtra("gubun",  "snooze");
        intent.putExtra("stop",   stopflag);
        int snooze = getSnoozeTime(context, aid);   
        //////////////////////////////////////////////////////////////
        intent.putExtra(AlarmMeta.COLUMNS.ALARM_SNOOZE,  snooze); 
        intent.putExtra(AlarmMeta.COLUMNS.ALARM_MEMO,    temp_Memo);
        intent.putExtra(AlarmMeta.COLUMNS.ALARM_PUZZLE, temp_Puzzle);
        intent.putExtra(AlarmMeta.COLUMNS.ALARM_TONE,    temp_Tone);
        intent.putExtra(AlarmMeta.COLUMNS.ALARM_VIB,     temp_Vib); 
        
/* I3.0 Code [START] */
        boolean isUseVolumeControl =  CommonUtil.isUseVolumeControl();
        if(isUseVolumeControl){
        	intent.putExtra(AlarmMeta.COLUMNS.ALARM_VOLUME, temp_AlarmVolume);
        }
/* I3.0 Code [END] */

		//////////////////////////////////////////////////////////////
        if (multiYN == true) {
        	intent.putExtra("multi",  "yes"); 
        }else {
        	intent.putExtra("multi",  "no"); 
        }
        
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, mintime, sender );
        android.util.Log.d(TAG, "RTC_WAKEUP is set in Alarms.java, snoozeSet");
        Calendar c3 = Calendar.getInstance();
        c3.setTimeInMillis( mintime  ) ; 
        Date dd1 =  c3.getTime();    
        Log.d(TAG, " Snooze Next ID - " + aid +  " --[[ Snooze Kind ]]----" + dd1.toString()); 
        
        ////////////////////////////////////////////////////////////////////////////////
        setStatusBarIcon(context, true);
        ////////////////////////////////////////////////////////////////////////////////
        String timeString = formatDayAndTime(context, c3);
        saveNextAlarm(context, timeString);
    }
    
    /**
     * snooze (Off / 5m / 10m/ 20m / 30m/ 60m)
     * @param id
     * @return
     */
    private static int getSnoozeTime(Context context, int alarmId) {
    	int snoozeSet = 0;   
        
        ContentResolver resolver = context.getContentResolver(); 
        
        boolean isUseVolumeControl =  CommonUtil.isUseVolumeControl();
        Cursor cc = null;
        try {
            cc = resolver.query(  ALProvider.CONTENT_ALARMS_URI, isUseVolumeControl ? ALARM_NEED_COLUMNS_2 : ALARM_NEED_COLUMNS, "_id=" + alarmId, null, null);
            if ( cc != null && cc.moveToFirst() ) {
                do {
                    snoozeSet   = cc.getInt(ALARM_NEED_COLUMNS_IDX_ALARM_SNOOZE);
                    if (!"Off".equalsIgnoreCase(cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_TONE))) {
                        temp_Tone =	cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_TONE);
                    } else {
                        temp_Tone =	"Off";
                    }
                    temp_Vib	= cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_VIB);
                    temp_Memo	= cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_MEMO);
                    temp_Puzzle = cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_PUZZLE);
                    
/* I3.0 Code [START] */
                    if(isUseVolumeControl){
                    	temp_AlarmVolume = cc.getString(ALARM_NEED_COLUMNS_IDX_ALARM_VOLUME);
                    }
/* I3.0 Code [END] */

                } while(cc.moveToNext());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cc != null)
                cc.close();
        }
        
        return snoozeSet;
    }
    
    /**
     * Disables alert in AlarmManger and StatusBar.
     *
     * @param id Alarm ID.
     * @param context Context
     */
    // On -> Off
    // [1] AlarmManager -> alarm setting cancel
    // [2] disable indicator 
    
    public static void disableAlert(Context context, int id) {
        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(ALARM_ALERT_ACTION);
        intent.putExtra("id", id);
           
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        am.cancel(sender);
                         
        setStatusBarIcon(context, false);
        saveNextAlarm(context, "");
    }

    /**
     * Tells the StatusBar whether the alarm is enabled or disabled
     */
    static void setStatusBarIcon(Context context, boolean enabled) {
    	Log.d(TAG, "setStatusBarIcon : "+enabled);
        Intent alarmChanged = new Intent(ACTION_ALARM_CHANGED);
        alarmChanged.putExtra("alarmSet", enabled);
        context.sendBroadcast(alarmChanged);
    }   

    /**
     * Given an alarm in hours and minutes, return a time suitable for
     * setting in AlarmManager.
     * @param hour Always in 24 hour 0-23
     * @param minute 0-59
     * @param daysOfWeek 0-59
    
     * @return Calendar */ 
    public static Calendar calculateAlarm(int hour, int minute, DaysOfWeek daysOfWeek) {

        // start with now
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());

        int nowHour = c.get(Calendar.HOUR_OF_DAY);
        int nowMinute = c.get(Calendar.MINUTE);

        // if alarm is behind current time, advance one day
        if (hour < nowHour  ||
            hour == nowHour && minute <= nowMinute) {
            c.add(Calendar.DAY_OF_YEAR, 1);
        }
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);

        int addDays = daysOfWeek.getNextAlarm(c);
        /* Log.v("** TIMES * " + c.getTimeInMillis() + " hour " + hour +
           " minute " + minute + " dow " + c.get(Calendar.DAY_OF_WEEK) + " from now " +
           addDays); */
        if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays);
        return c;
    }

    static String formatTime(final Context context, int hour, int minute,
                             DaysOfWeek daysOfWeek) {
        Calendar c = calculateAlarm(hour, minute, daysOfWeek);
        return formatTime(context, c);
    } 
    
    /* used by AlarmAlert */
    static String formatTime(final Context context, Calendar c) {
        String format = get24HourMode(context) ? M24 : M12;
        return (c == null) ? "" : (String)DateFormat.format(format, c);
    }

    /**
     * Shows day and time -- used for lock screen
     */
    private static String formatDayAndTime(final Context context, Calendar c) {
        String format = get24HourMode(context) ? DM24 : DM12;
        return (c == null) ? "" : (String)DateFormat.format(format, c);
    }

    /**
     * Save time of the next alarm, as a formatted string, into the system
     * settings so those who care can make use of it.
     */
    static void saveNextAlarm(final Context context, String timeString) {
        Settings.System.putString(context.getContentResolver(),
                                  Settings.System.NEXT_ALARM_FORMATTED,
                                  timeString);
    }    
   
    /**
     * @return true if clock is set to 24-hour mode
     */
    static boolean get24HourMode(final Context context) {
        return android.text.format.DateFormat.is24HourFormat(context);
    }
    /////////////////////////////////////////////////////////////////////////////////////////
	/**
     *  repeat check function
     *  if this function return value is true, this is not repeat  
     * @param context
    
    
     * @param id int
	 * @param tag boolean
	 */
    public static void noRepeatChecking(Context context, int id, boolean tag){
    	ContentResolver resolver = context.getContentResolver();
    	final String[] alarmNeedColums = { "daysofweek" };
        boolean check = false;
        Cursor cc = null;
        try {
            cc = resolver.query(  ALProvider.CONTENT_ALARMS_URI, alarmNeedColums, "_id=" + id, null, null );
            if ( cc != null && cc.moveToFirst() ) {
                if (cc.getInt(0) == 0) {
                    Log.d(TAG, "NotRepeatedCheck YES=>");
                    check = true;
                } else {
                    Log.d(TAG, "NotRepeatedCheck NO=>");
                }
            } 
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cc != null)
                cc.close();
        }

		// enabled value &  id value update
        if (check == true) {
            enableAlarmInternalOff(context, id, tag);  
        } 
    } 
}  

     